﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Task.cs" company="DHGMS Solutions">
//   2004-2012 DHGMS Solutions. Some Rights Reserved. Licensed under GNU General Public License version 2 (GPLv2)
// </copyright>
// <summary>
//   Helper methods for tasks
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Dhgms.TplHelper.Model.Helper
{
    using System;
    using System.Diagnostics;
    using System.Threading.Tasks;

    using Dhgms.TplHelper.Model.Info;
    using Dhgms.TplHelper.Model.Info.JobResult;
    using Dhgms.TplHelper.Model.Info.TaskResult;
    using Dhgms.TplHelper.Model.TaskHelper;

    /// <summary>
    /// Helper methods for tasks
    /// </summary>
    public static class Task
    {
        /// <summary>
        /// Runs a task instantly
        /// </summary>
        /// <param name="task">
        /// The task to run.
        /// </param>
        /// <typeparam name="TTaskClass">
        /// The type of the task being run
        /// </typeparam>
        /// <typeparam name="TResultClass">
        /// The type of the result information being returned
        /// </typeparam>
        /// <returns>
        /// Job Result Information
        /// </returns>
        public static TResultClass Execute<TTaskClass, TResultClass>(TTaskClass task)
            where TResultClass : TaskResultBase, new()
            where TTaskClass : BaseTaskHelper<TResultClass>
        {
            if (task == null)
            {
                throw new ArgumentNullException("task");
            }

            if (Debugger.IsAttached)
            {
                return task.Execute();
            }

            var t = task.Task;
            t.RunSynchronously();

            if (!task.Task.IsFaulted)
            {
                return task.Task.Result;
            }

            if (t.Exception == null)
            {
                throw new TaskCanceledException();
            }

            if (t.Exception.InnerExceptions != null && t.Exception.InnerExceptions.Count == 1)
            {
                throw t.Exception.InnerExceptions[0];
            }

            throw t.Exception;
        }

        /// <summary>
        /// Executes a job, adds the result to the TaskResultCollection and returns the internal data. Used to streamline some
        /// common functionality.
        /// </summary>
        /// <param name="task">
        /// The task.
        /// </param>
        /// <param name="taskResultCollection">
        /// The task result collection.
        /// </param>
        /// <typeparam name="TTaskClass">
        /// Type for the task class.
        /// </typeparam>
        /// <typeparam name="TResultClass">
        /// Type for the task result.
        /// </typeparam>
        /// <typeparam name="TTaskDataType">
        /// Type for the Task Result Data Type.
        /// </typeparam>
        /// <returns>
        /// The task Result
        /// </returns>
        public static TTaskDataType GetExecutionData<TTaskClass, TResultClass, TTaskDataType>(TTaskClass task, TaskCollection taskResultCollection)
            where TResultClass : TaskResultBase, ITaskDataResult<TTaskDataType>, new()
            where TTaskClass : BaseTaskHelper<TResultClass>
        {
            if (task == null)
            {
                throw new ArgumentNullException("task");
            }

            if (taskResultCollection == null)
            {
                throw new ArgumentNullException("taskResultCollection");
            }

            var taskResult = Execute<TTaskClass, TResultClass>(task);
            taskResultCollection.TaskResults.Add(taskResult);

            return taskResult.Data;
        }
    }
}
